package com.yswee.framework.utils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import org.json.JSONTokener;

public class JsonUtils {

	private JsonUtils() {
        // should never be instantiated
        throw new AssertionError();
    }

    private static ThreadLocal<Map<String, SimpleDateFormat>> formatMap = new ThreadLocal<Map<String, SimpleDateFormat>>() {
        @Override
        protected Map<String, SimpleDateFormat> initialValue() {
            return new HashMap<String, SimpleDateFormat>();
        }
    };

    public static String[] getStringArray(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return new String[0];
            } else {
                JSONArray ja = json.getJSONArray(name);
                String[] array = new String[ja.length()];
                for(int i = 0; i < ja.length(); i++) {
                	array[i] = ja.getString(i);
                }
                return array;
            }
        } catch (Exception jsone) {
            return new String[0];
        }
    }

    public static String getString(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return "";
            } else {
                return json.getString(name);
            }
        } catch (Exception jsone) {
            return "";
        }
    }

    public static Date getDate(String name, JSONObject json) {
        return getDate(name, json, "EEE MMM d HH:mm:ss z yyyy");
    }

    public static Date getDate(String name, JSONObject json, String format) {
        String dateStr = getString(name, json);
        if ("null".equals(dateStr) || null == dateStr || dateStr.equals("")) {
            return null;
        } else {
            return getDate(dateStr, format);
        }
    }

    public static Date getDate(String name, String format) {
        SimpleDateFormat sdf = formatMap.get().get(format);
        if (null == sdf) {
            sdf = new SimpleDateFormat(format, Locale.ENGLISH);
            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
            formatMap.get().put(format, sdf);
        }
        try {
            return sdf.parse(name);
        } catch (ParseException pe) {
        	LogcatUtils.e("JsonUtils", pe);
        	return new Date(0);
        }
    }

    public static int getInt(String name, JSONObject elem) {
    	try {
	        String str2 = getString(name, elem);
	        if (null == str2 || "".equals(str2) || "null".equals(str2)) {
	            return -1;
	        } else {
	            return Integer.valueOf(str2);
	        }
    	} catch (Exception e) {
        	LogcatUtils.e("JsonUtils", e);
    		return -1;
    	}
    }

    public static int[] getIntArray(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return new int[0];
            } else {
                JSONArray ja = json.getJSONArray(name);
                int[] array = new int[ja.length()];
                for(int i = 0; i < ja.length(); i++) {
                	array[i] = ja.getInt(i);
                }
                return array;
            }
        } catch (Exception jsone) {
            return new int[0];
        }
    }

    public static long getLong(String name, JSONObject json) {
    	try {
	        String str2 = getString(name, json);
	        if (null == str2 || "".equals(str2) || "null".equals(str2)) {
	            return -1;
	        } else {
	            return Long.valueOf(str2);
	        }
    	} catch (Exception e) {
        	LogcatUtils.e("JsonUtils", e);
    		return -1;
    	}
    }

    public static long[] getLongArray(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return new long[0];
            } else {
                JSONArray ja = json.getJSONArray(name);
                long[] array = new long[ja.length()];
                for(int i = 0; i < ja.length(); i++) {
                	array[i] = ja.getLong(i);
                }
                return array;
            }
        } catch (Exception jsone) {
            return new long[0];
        }
    }

    public static float getFloat(String name, JSONObject json) {
        try {
        	String str2 = getString(name, json);
	        if (null == str2 || "".equals(str2) || "null".equals(str2)) {
	            return -1;
	        } else {
	            return Float.valueOf(str2);
	        }
    	} catch (Exception e) {
        	LogcatUtils.e("JsonUtils", e);
    		return -1;
    	}
    }

    public static float[] getFloatArray(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return new float[0];
            } else {
                JSONArray ja = json.getJSONArray(name);
                float[] array = new float[ja.length()];
                for(int i = 0; i < ja.length(); i++) {
                	array[i] = (float) ja.getDouble(i);
                }
                return array;
            }
        } catch (Exception jsone) {
            return new float[0];
        }
    }

    public static double getDouble(String name, JSONObject json) {
        try {
        	String str2 = getString(name, json);
	        if (null == str2 || "".equals(str2) || "null".equals(str2)) {
	            return -1;
	        } else {
	            return Double.valueOf(str2);
	        }
    	} catch (Exception e) {
        	LogcatUtils.e("JsonUtils", e);
    		return -1;
    	}
    }

    public static double[] getDoubleArray(String name, JSONObject json) {
        try {
            if (json.isNull(name)) {
                return new double[0];
            } else {
                JSONArray ja = json.getJSONArray(name);
                double[] array = new double[ja.length()];
                for(int i = 0; i < ja.length(); i++) {
                	array[i] = ja.getDouble(i);
                }
                return array;
            }
        } catch (Exception jsone) {
            return new double[0];
        }
    }

    public static boolean getBoolean(String name, JSONObject json) {
    	try {
	        String str = getString(name, json);
	        if (null == str || "null".equals(str)) {
	            return false;
	        }
	        return Boolean.valueOf(str);
    	} catch (Exception e) {
        	LogcatUtils.e("JsonUtils", e);
    		return false;
    	}
    }

    public static JSONObject asJSONObject(String res) {
        JSONObject ret = null;
        try {
            ret = new JSONObject(new JSONTokener(res));
        } catch (Exception jsone) {
        	LogcatUtils.e("JsonUtils", jsone);
        }
        return ret;
    }

    public static JSONArray asJSONArray(String res) {
        JSONArray ret = null;
        try {
            ret = new JSONArray(new JSONTokener(res));
        } catch (Exception jsone) {
        	LogcatUtils.e("JsonUtils", jsone);
        }
        return ret;
    }
    
    
    /** JSON序列化 **/

	/** 将对象转换成Json字符串 **/
	public static String toJSON(Object obj) {
		JSONStringer js = new JSONStringer();
		serialize(js, obj);
		return js.toString();
	}

	/** 序列化为JSON **/
	private static void serialize(JSONStringer js, Object o) {
		if (isNull(o)) {
			try {
				js.value(null);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return;
		}
		Class<?> clazz = o.getClass();
		if (ClassUtils.isObject(clazz)) { // 对象
			serializeObject(js, o);
		} else if (ClassUtils.isArray(clazz)) { // 数组
			serializeArray(js, o);
		} else if (ClassUtils.isCollection(clazz)) { // 集合
			Collection<?> collection = (Collection<?>) o;
			serializeCollect(js, collection);
		} else { // 单个值
			try {
				js.value(o);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/** 序列化数组 **/
	private static void serializeArray(JSONStringer js, Object array) {
		try {
			js.array();
			for (int i = 0; i < Array.getLength(array); ++i) {
				Object o = Array.get(array, i);
				serialize(js, o);
			}
			js.endArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** 序列化集合 **/
	private static void serializeCollect(JSONStringer js,
			Collection<?> collection) {
		try {
			js.array();
			for (Object o : collection) {
				serialize(js, o);
			}
			js.endArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 序列化对象
	 * **/
	private static void serializeObject(JSONStringer js, Object obj) {
		try {
			js.object();
			for (Field f : obj.getClass().getFields()) {
				Object o = f.get(obj);
				js.key(f.getName());
				serialize(js, o);
			}
			js.endObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 反序列化简单对象
	 * @throws
	 **/
	public static <T> T parseObject(JSONObject jo, Class<T> clazz) {
		if (clazz == null || isNull(jo)) {
			return null;
		}
		T obj = createInstance(clazz);
		if (obj == null) {
			return null;
		}
		for (Field f : clazz.getFields()) {
			setField(obj, f, jo);
		}
		return obj;
	}

	/**
	 * 反序列化简单对象
	 * @throws
	 **/
	public static <T> T parseObject(String jsonString, Class<T> clazz) {
		if (clazz == null || jsonString == null || jsonString.length() == 0) {
			return null;
		}
		JSONObject jo = null;
		try {
			jo = new JSONObject(jsonString);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (isNull(jo)) {
			return null;
		}
		return parseObject(jo, clazz);
	}

	/**
	 * 
	 * 反序列化数组对象
	 * @throws
	 **/
	public static <T> T[] parseArray(JSONArray ja, Class<T> clazz) {
		if (clazz == null || isNull(ja)) {
			return null;
		}
		int len = ja.length();
		@SuppressWarnings("unchecked")
		T[] array = (T[]) Array.newInstance(clazz, len);
		for (int i = 0; i < len; ++i) {
			try {
				JSONObject jo = ja.getJSONObject(i);
				T o = parseObject(jo, clazz);
				array[i] = o;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return array;
	}

	/**
	 * 
	 * 反序列化数组对象
	 * @throws
	 **/
	public static <T> T[] parseArray(String jsonString, Class<T> clazz) {
		if (clazz == null || jsonString == null || jsonString.length() == 0) {
			return null;
		}
		JSONArray jo = null;
		try {
			jo = new JSONArray(jsonString);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (isNull(jo)) {
			return null;
		}
		return parseArray(jo, clazz);
	}

	/**
	 * 
	 * 反序列化泛型集合
	 * @throws
	 **/
	@SuppressWarnings("unchecked")
	public static <T> Collection<T> parseCollection(JSONArray ja,
			Class<?> collectionClazz,
			Class<T> genericType) {
		if (collectionClazz == null || genericType == null || isNull(ja)) {
			return null;
		}
		Collection<T> collection = (Collection<T>) createInstance(collectionClazz);
		for (int i = 0; i < ja.length(); ++i) {
			try {
				JSONObject jo = ja.getJSONObject(i);
				T o = parseObject(jo, genericType);
				collection.add(o);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return collection;
	}

	/**
	 * 
	 * 反序列化泛型集合
	 * @throws
	 **/
	public static <T> Collection<T> parseCollection(String jsonString,
			Class<?> collectionClazz,
			Class<T> genericType) {
		if (collectionClazz == null || genericType == null
				|| jsonString == null
				|| jsonString.length() == 0) {
			return null;
		}
		JSONArray jo = null;
		try {
			jo = new JSONArray(jsonString);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (isNull(jo)) {
			return null;
		}
		return parseCollection(jo, collectionClazz, genericType);
	}

	/** 根据类型创建对象 **/
	private static <T> T createInstance(Class<T> clazz) {
		if (clazz == null)
			return null;
		T obj = null;
		try {
			obj = clazz.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;
	}

	/** 设定字段的值 **/
	private static void setField(Object obj, Field f, JSONObject jo) {
		String name = f.getName();
		Class<?> clazz = f.getType();
		try {
			if (ClassUtils.isArray(clazz)) { // 数组
				Class<?> c = clazz.getComponentType();
				JSONArray ja = jo.optJSONArray(name);
				if (!isNull(ja)) {
					Object array = parseArray(ja, c);
					f.set(obj, array);
				}
			} else if (ClassUtils.isCollection(clazz)) { // 泛型集合
				// 获取定义的泛型类型
				Class<?> c = null;
				Type gType = f.getGenericType();
				if (gType instanceof ParameterizedType) {
					ParameterizedType ptype = (ParameterizedType) gType;
					Type[] targs = ptype.getActualTypeArguments();
					if (targs != null && targs.length > 0) {
						Type t = targs[0];
						c = (Class<?>) t;
					}
				}
				JSONArray ja = jo.optJSONArray(name);
				if (!isNull(ja)) {
					Object o = parseCollection(ja, clazz, c);
					f.set(obj, o);
				}
			} else if (ClassUtils.isSingle(clazz)) { // 值类型
				Object o = jo.opt(name);
				if (o != null) {
					f.set(obj, o);
				}
			} else if (ClassUtils.isObject(clazz)) { // 对象
				JSONObject j = jo.optJSONObject(name);
				if (!isNull(j)) {
					Object o = parseObject(j, clazz);
					f.set(obj, o);
				}
			} else {
				throw new Exception("unknow type!");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** 判断对象是否为空 **/
	private static boolean isNull(Object obj) {
		if (obj instanceof JSONObject) {
			return JSONObject.NULL.equals(obj);
		}
		return obj == null;
	}
	
	public static HashMap<String, Object> toHashMap(JSONObject object) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		Object value;
		String key;
		for (Iterator<?> it = object.keys(); it.hasNext();) {
			key = (String) it.next();
			if (object.isNull(key)) {
				map.put(key, null);
			} else {
				try {
					value = object.get(key);
					if (value instanceof JSONArray) {
						value = toList((JSONArray) value);
					} else if (value instanceof JSONObject) {
						value = toHashMap((JSONObject) value);
					}
					map.put(key, value);
				} catch (JSONException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}

	private static List<Object> toList(JSONArray array) {
		List<Object> list = new ArrayList<Object>();
		Object value;
		for (int i = 0; i < array.length(); i++) {
			try {
				value = array.get(i);
				if (value instanceof JSONArray) {
					value = toList((JSONArray) value);
				} else if (value instanceof JSONObject) {
					value = toHashMap((JSONObject) value);
				}
				list.add(value);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return list;
	}
	
}
